package com.syh.jn.scm.service.impl.upstream.logistics;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.supplier.entity.logistics.LogisticsBill;
import com.syh.jn.scm.domain.supplier.event.LogisticsBillEvent;
import com.syh.jn.scm.domain.upstream.entity.logistics.UpLogisticsBill;
import com.syh.jn.scm.domain.upstream.entity.logistics.UpLogisticsBillItem;
import com.syh.jn.scm.domain.upstream.entity.sale.UpSaleOrder;
import com.syh.jn.scm.domain.upstream.event.UpLogisticsBillEvent;
import com.syh.jn.scm.domain.upstream.repository.logistics.UpLogisticsBillRepository;
import com.syh.jn.scm.domain.upstream.repository.sale.UpSaleOrderRepository;
import com.syh.jn.scm.dto.upstream.logistics.UpLogisticsBillItemVo;
import com.syh.jn.scm.dto.upstream.logistics.UpLogisticsBillMto;
import com.syh.jn.scm.dto.upstream.logistics.UpLogisticsBillSto;
import com.syh.jn.scm.dto.upstream.logistics.UpLogisticsBillVo;
import com.syh.jn.scm.service.api.supplier.logistics.enums.LogisticsBillEnums;
import com.syh.jn.scm.service.api.upstream.logistics.UpLogisticsBillService;
import com.syh.jn.scm.service.api.upstream.logistics.enums.UpLogisticsBillEnum;
import com.syh.jn.scm.service.api.upstream.sale.enums.UpSaleOrderEnums;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by soci.song on 2018/11/2.
 */
@Service
@Transactional
public class UpLogisticsBillServiceImpl extends AbstractServiceImpl<UpLogisticsBillSto, UpLogisticsBillMto, UpLogisticsBillVo, UpLogisticsBill, Long> implements UpLogisticsBillService {
  @Autowired
  private UpLogisticsBillRepository upLogisticsBillRepository;
  @Autowired
  private UpSaleOrderRepository upSaleOrderRepository;

  @Override
  protected AggregateRepository<UpLogisticsBill, Long> getAggregateRepository() {
    return upLogisticsBillRepository;
  }

  /**
   * 创建物流单
   *
   * @param upLogisticsBillSto
   * @return
   */
  @Override
  public Long save(UpLogisticsBillSto upLogisticsBillSto) {
    UpLogisticsBill upLogisticsBill = new UpLogisticsBill(upLogisticsBillSto);
    Long id = upLogisticsBillRepository.add(upLogisticsBill);
    upLogisticsBill.setId(id);
    UpSaleOrder upSaleOrder = upSaleOrderRepository.getById(upLogisticsBill.getOrderId());
    this.publicEvent(UpLogisticsBillEvent.bulidUpLogisticsBillCreated(new Object[]{upLogisticsBill}));
    //如果是直采直销的采购物流单创建
    if (upSaleOrder.getOrderType().equals(UpSaleOrderEnums.OrderType.PURCHASE_SALE.getStatus())) {
      this.publicEvent(UpLogisticsBillEvent.bulidPurchaseSaleLogisticsBillCreated(new Object[]{upLogisticsBill}));
    }
    //当不是物流发货时,自动出车
    if (!upLogisticsBillSto.getDeliveryType().equals(UpLogisticsBillEnum.DeliveryType.LOGISTICS_TYPE.getDeliveryType())) {
      this.delivery(id);
    }
    return id;
  }

  /**
   * 修改物流单
   *
   * @param mto
   */
  @Override
  public void update(UpLogisticsBillMto mto) {
    UpLogisticsBill logisticsBill = judgeNull(mto.getId());
    logisticsBill.modify(mto);
    upLogisticsBillRepository.update(logisticsBill);
    UpSaleOrder upSaleOrder = upSaleOrderRepository.getById(logisticsBill.getOrderId());
    if (upSaleOrder.getOrderType().equals(UpSaleOrderEnums.OrderType.PURCHASE_SALE.getStatus())) {
      List<UpLogisticsBillItem> items = upLogisticsBillRepository.getItemsByLogisticsBillId(logisticsBill.getId());
      logisticsBill.setItems(items);
      this.publicEvent(UpLogisticsBillEvent.bulidPurchaseSaleLogisticsBillUpdated(new Object[]{logisticsBill}));
    }
  }

  @Override
  public void delivery(Long id) {
    UpLogisticsBill logisticsBill = upLogisticsBillRepository.getById(id);
    logisticsBill.delivery();
    upLogisticsBillRepository.updateStatus(logisticsBill);
    UpSaleOrder upSaleOrder = upSaleOrderRepository.getById(logisticsBill.getOrderId());
    //TODO 直采直销发货不同步
//    if (upSaleOrder.getOrderType().equals(UpSaleOrderEnums.OrderType.PURCHASE_SALE.getStatus())) {
//      this.publicEvent(UpLogisticsBillEvent.bulidPurchaseSaleLogisticsBillDelivery(new Object[]{logisticsBill}));
//    }
    this.publicEvent(UpLogisticsBillEvent.bulidUpLogisticsBillDelivery(new Object[]{logisticsBill}));
  }

  @Override
  public void collect(Long id) {
    UpLogisticsBill logisticsBill = upLogisticsBillRepository.getById(id);
    logisticsBill.collect();
    upLogisticsBillRepository.updateStatus(logisticsBill);
    this.publicEvent(UpLogisticsBillEvent.bulidUpLogisticsBillCollected(new Object[]{logisticsBill}));
  }

  @Override
  public void cancel(Long id) {
    UpLogisticsBill logisticsBill = upLogisticsBillRepository.getById(id);
    logisticsBill.cancel();
    upLogisticsBillRepository.updateStatus(logisticsBill);
    UpSaleOrder upSaleOrder = upSaleOrderRepository.getById(logisticsBill.getOrderId());
    if (upSaleOrder.getOrderType().equals(UpSaleOrderEnums.OrderType.PURCHASE_SALE.getStatus())) {
      this.publicEvent(UpLogisticsBillEvent.bulidPurchaseSaleLogisticsBillCancelled(new Object[]{logisticsBill}));
    }
    this.publicEvent(UpLogisticsBillEvent.bulidUpLogisticsBillCancelled(new Object[]{logisticsBill}));

  }

  /**
   * 消费者(监听服务商采购取消签收)
   *
   * @param logisticsBill
   */
  @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_UN_RECEIVED)
  public void handelLogisticsBillUnReceived(LogisticsBill logisticsBill,LogisticsBill oldLogisticsBill) {
    if (!logisticsBill.getDeliveryType().equals(LogisticsBillEnums.DeliveryType.LOGISTICS_TYPE.getDeliveryType())) {
      //如果是上游销售的取消签收 则一起取消发货
      if (logisticsBill.getOrderType().equals(UpLogisticsBillEnum.ORDER_TYPE_SALE.getStatus())) {
        this.cancel(logisticsBill.getId());
      }

    }
  }

  @Override
  public void cancelReceipt(Long id) {
    UpLogisticsBill logisticsBill = upLogisticsBillRepository.getById(id);
    UpLogisticsBill oldBill = upLogisticsBillRepository.getById(id);
    logisticsBill.cancelReceipt();
    upLogisticsBillRepository.updateStatus(logisticsBill);
    this.publicEvent(UpLogisticsBillEvent.bulidUpLogisticsBillUnReceived(new Object[]{logisticsBill,oldBill}));
  }

  @Override
  public void remove(Long id) {
    UpLogisticsBill logisticsBill = upLogisticsBillRepository.getById(id);
    //如果不是物流发货 且是已发货状态 则先取消出车
    if (!logisticsBill.getDeliveryType().equals(UpLogisticsBillEnum.DeliveryType.LOGISTICS_TYPE.getDeliveryType())
            && logisticsBill.getLogisticsState().equals(UpLogisticsBillEnum.DRIVER_DELIVEED.getStatus())) {
      this.cancel(id);
      logisticsBill = upLogisticsBillRepository.getById(id);
    }
    logisticsBill.remove();
    upLogisticsBillRepository.removeById(id);
    UpSaleOrder upSaleOrder = upSaleOrderRepository.getById(logisticsBill.getOrderId());
    this.publicEvent(UpLogisticsBillEvent.bulidUpLogisticsBillDeleted(new Object[]{logisticsBill}));
    //如果是直采直销的采购物流单删除
    if (upSaleOrder.getOrderType().equals(UpSaleOrderEnums.OrderType.PURCHASE_SALE.getStatus())) {
      this.publicEvent(UpLogisticsBillEvent.bulidPurchaseSaleLogisticsBillDeleted(new Object[]{id}));
    }
  }

  /**
   * 判空方法
   *
   * @param id
   * @return
   */
  private UpLogisticsBill judgeNull(Long id) {
    ExtAssert.notNull(id, "id不能为空");
    UpLogisticsBill entity = upLogisticsBillRepository.getById(id);
    ExtAssert.notNull(entity, "订单不存在");
    return entity;
  }

  @Override
  public List<UpLogisticsBillItemVo> getItemsByLogisticsBillId(Long id) {
    return transformLogistics(upLogisticsBillRepository.getItemsByLogisticsBillId(id));
  }

  @Override
  public List<UpLogisticsBillVo> getLogisticsBillVosByOrderId(Long id, Short orderType) {
    Wrapper we = Wrapper.build();
    we.append(Restrictions.eq("orderType", orderType));
    we.append(Restrictions.eq("orderId", id));
    List<UpLogisticsBillVo> billVos = upLogisticsBillRepository.getListView(we);
    billVos.forEach(vo -> {
      List<UpLogisticsBillItemVo> itemVos = transformLogistics(upLogisticsBillRepository.getItemsByLogisticsBillId(vo.getId()));
      vo.setItems(itemVos);
    });
    return billVos;
  }

  /**
   * 内部方法  领域对象转vo
   *
   * @param entityList
   * @return
   */
  private List<UpLogisticsBillItemVo> transformLogistics(List<UpLogisticsBillItem> entityList) {
    List<UpLogisticsBillItemVo> voList = new ArrayList<>();
    entityList.stream().forEach((entity) -> {
      UpLogisticsBillItemVo vo = new UpLogisticsBillItemVo();
      ExtBeanUtils.copyProperties(entity, vo);
      voList.add(vo);
    });
    return voList;
  }

  private UpLogisticsBillItemVo trans(UpLogisticsBillItem entity) {
    UpLogisticsBillItemVo vo = new UpLogisticsBillItemVo();
    ExtBeanUtils.copyProperties(entity, vo);
    return vo;
  }
}
